#include <string.h>
#include <stdio.h>
#include "mhscpu.h"
#include "mh_sm3.h"
#include "debug.h"

#define c_sm3_len       16
#define c_sm3_msg       "0102030405060708090a0b0c0d0e0f10"
#define c_sm3_hash      "25C9D66ED547714E981BC825B969CC71ACD338F90A4E0F75E789EF71C0921666"

uint32_t SM3_check(void)
{   
    uint32_t ret = 0;
    
    uint32_t t,i;
    uint8_t Message[16] = {0};
    uint8_t Hash[32] = {0};
    uint8_t _Hash[32] = {0}; 

    bn_read_string_to_bytes(Message, sizeof(Message), c_sm3_msg);
    bn_read_string_to_bytes(_Hash, sizeof(_Hash), c_sm3_hash);
                        
    mh_sm3(Hash, Message, c_sm3_len);
                        
    t = memcmp(Hash, _Hash, sizeof(_Hash));
    
    if(0 != t)
    {
        ret = 1;
        //printf("\nSM3_check check fault!\n");
    }
    
    return ret;
}

void test_SM3(void)
{
    uint32_t t;
    char s[40] = {0};
    uint8_t Message0[] = "abc";
    uint8_t Message1[] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd";
    uint8_t Hash[32];
    uint8_t Len;
    uint8_t mHash0[] = {0x66, 0xC7, 0xF0, 0xF4, 0x62, 0xEE, 0xED, 0xD9, 0xD1, 0xF2, 0xD4, 0x6B, 0xDC, 0x10, 0xE4, 0xE2,
                        0x41, 0x67, 0xC4, 0x87, 0x5C, 0xF2, 0xF7, 0xA2, 0x29, 0x7D, 0xA0, 0x2B, 0x8F, 0x4B, 0xA8, 0xE0}; 
    uint8_t mHash1[] = {0xde, 0xbe, 0x9f, 0xf9, 0x22, 0x75, 0xb8, 0xa1, 0x38, 0x60, 0x48, 0x89, 0xc1, 0x8e, 0x5a, 0x4d,
                        0x6f, 0xdb, 0x70, 0xe5, 0x38, 0x7e, 0x57, 0x65, 0x29, 0x3d, 0xcb, 0xa3, 0x9c, 0x0c, 0x57, 0x32}; 

    DBG_PRINTF("\nSM3 Test In\n");
                        
    Len = sizeof(Message0) - 1;
    mh_sm3(Hash, Message0, Len);
    sprintf(s, "SM3 mh_sm3 Test %d\n", Len * 8);
    t = (!memcmp(Hash, mHash0, sizeof(mHash0)));
    r_printf(t, s);

    Len = sizeof(Message1) - 1;
    mh_sm3(Hash, Message1, Len);
    sprintf(s, "SM3 mh_sm3 Test %d\n", Len * 8);
    t = (!memcmp(Hash, mHash1, sizeof(mHash1)));
    r_printf(t, s);
    
    
    {
//      mh_sm3_list_def list[3];
//      mh_list_init(&list[0], NULL, 0);
//      mh_list_init(&list[1], NULL, 0);
//      mh_list_init(&list[2], NULL, 0);
//      ms_list_append(list, &list[1]);
//      ms_list_append(list, &list[2]);
//      mh_list_set(&list[0], &Message0[0], 1);
//      mh_list_set(&list[1], &Message0[1], 1);
//      mh_list_set(&list[2], &Message0[2], 1);
//      
//      Len = sizeof(Message0) - 1;
//      mh_sm3_list(Hash, list);
//      if(!memcmp(Hash, mHash0, sizeof(mHash0)))
//          DBG_PRINTF("SM3 mh_sm3_list Test %d Pass...\n", Len * 8);
//      else
//          DBG_PRINTF("SM3 mh_sm3_list Test %d Fail...\n", Len * 8);


//      list[0].data = Message1;
//      list[0].size = 7;
//      list[1].data = Message1 + list[0].size;
//      list[1].size = 9;
//      list[2].data = Message1 + list[0].size + list[1].size;
//      list[2].size = 48;      
//      
//      Len = sizeof(Message1) - 1;
//      mh_list_set(&list[0], Message1, 7);
//      mh_list_set(&list[1], Message1 + list[0].size, 9);
//      mh_list_set(&list[2], Message1 + list[0].size + list[1].size, 48);
//      
//      mh_sm3_list(Hash, list);
//      if(!memcmp(Hash, mHash1, sizeof(mHash1)))
//          DBG_PRINTF("SM3 mh_sm3_list Test %d Pass...\n", Len * 8);
//      else
//          DBG_PRINTF("SM3 mh_sm3_list Test %d Fail...\n", Len * 8);
    }
        
        
    
    
    //print_hex("Hash:", Hash, sizeof(Hash));
#if USE_TIME_DEBUG
    BEGIN_TEST();
    mh_sm3(Hash, Message0, Len);
    END_TEST();
    DBG_PRINTF("Hash_time = %dus\n", t/FCLK);
#endif
}


void mh_SM3_test_with_known_data(void)
{
    uint32_t t, len;
    char s[40] = {0};
    uint8_t Message0[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
                            0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
                            0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
                            0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
                            0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
                            0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
                            0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
                            0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
                            0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
                            0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
                            0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
                            0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
                            0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
                            0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
                            0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
                            0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,
                            0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
                            0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
                            0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
                            0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
                            0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
                            0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
                            0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
                            0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
                            0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f};
        
    uint8_t Hash[32];
    uint8_t Hash_300Bytes[][32] = {0x11,0xf3,0x94,0x0f,0x10,0xce,0x70,0xef,0x1f,0x7b,0xd8,0x03,0x2b,0x0a,0x72,0x8b,0x11,0x24,0xe5,0x2c,0xe7,0x8c,0x04,0x8f,0x10,0x90,0x36,0x77,0x76,0xfe,0xb2,0xe4};
    uint8_t Hash_54Bytes[32] = {0x1b,0xb1,0xb5,0x92,0x23,0x94,0x47,0xb5,0xde,0x03,0x95,0xd9,0x41,0x59,0x99,0x6e,0xa7,0xcc,0x4f,0xcc,0x7b,0x9f,0x66,0xcc,0xc5,0xf0,0xcf,0xdc,0x89,0x58,0x67,0x82};
    uint8_t Hash_55Bytes[32] = {0xa7,0x9c,0xf9,0xdc,0xee,0x34,0x04,0xab,0xf7,0xf7,0x69,0x69,0x82,0x01,0x64,0x7f,0xd9,0xd3,0xff,0x61,0xd6,0x29,0xd0,0xf5,0x8b,0xb4,0xb5,0x57,0x9a,0x42,0x7d,0xb8};
    uint8_t Hash_56Bytes[32] = {0x62,0xf7,0x36,0x3b,0x15,0xf4,0xde,0x76,0xdd,0x92,0x5c,0x49,0x3b,0x9d,0x6d,0x00,0xd4,0xba,0x0e,0xf2,0xa1,0xf3,0x34,0xc1,0xd0,0xf1,0x3b,0x29,0x3a,0xeb,0x40,0xd1};
    uint8_t Hash_65Bytes[32] = {0xc8,0x86,0xe6,0x81,0x4b,0xe7,0x48,0x28,0x5a,0x10,0xb2,0x8a,0xe6,0x2d,0xda,0xcd,0x85,0xdb,0x83,0x0c,0xd2,0xcf,0x3a,0x2b,0xfa,0x2f,0x72,0x9c,0x15,0xf6,0x36,0x18};
    uint8_t Hash_64_4_54Bytes[32] = {0x5e,0x3c,0x51,0x50,0xf9,0x9f,0x92,0x1a,0x18,0xc8,0x4a,0x25,0x19,0xed,0xc6,0x25,0xe8,0xd5,0xc7,0x21,0x25,0x18,0x02,0x17,0x8d,0xa7,0x90,0x83,0x53,0xbe,0xd0,0xfe};
    uint8_t Hash_64_4_55Bytes[32] = {0xbd,0xc8,0xf8,0x3e,0xbb,0xcd,0x14,0x02,0xbe,0x68,0xab,0x38,0x87,0x98,0x71,0x30,0x18,0xf0,0x40,0x30,0x15,0x92,0x18,0xf2,0x4e,0xe2,0xd7,0xc6,0xd7,0x1c,0xa1,0xf2};
    uint8_t Hash_64_4_56Bytes[32] = {0x53,0xc5,0x7a,0xa4,0xaa,0xd0,0x18,0x0c,0xe1,0x07,0x01,0x73,0x96,0x0e,0xfb,0x0f,0xe0,0xd2,0x40,0xe4,0x57,0x42,0x66,0x3c,0x20,0x2e,0x48,0xe9,0x96,0x14,0xde,0x73};

    uint8_t *pu8In;
    sm3_context ctx;
        
    DBG_PRINTF("\n%s\n",__func__);
            
    memset(Hash, 0, sizeof(Hash));
    mh_sm3(Hash, Message0, 300);
    sprintf(s, "SM3 mh_sm3 Test %d\n", 300 * 8);
    t = (!memcmp(Hash, Hash_300Bytes, sizeof(Hash)));
    r_printf(t, s);

    memset(Hash, 0, sizeof(Hash));
    mh_sm3(Hash, Message0, 54);
    sprintf(s, "SM3 mh_sm3 Test %d\n", 54 * 8);
    t = (!memcmp(Hash, Hash_54Bytes, sizeof(Hash)));
    r_printf(t, s);
        
    memset(Hash, 0, sizeof(Hash));
    mh_sm3(Hash, Message0, 55);
    sprintf(s, "SM3 mh_sm3 Test %d\n", 55 * 8);
    t = (!memcmp(Hash, Hash_55Bytes, sizeof(Hash)));
    r_printf(t, s);
    
    memset(Hash, 0, sizeof(Hash));
    mh_sm3(Hash, Message0, 56);
    sprintf(s, "SM3 mh_sm3 Test %d\n", 56 * 8);
    t = (!memcmp(Hash, Hash_56Bytes, sizeof(Hash)));
    r_printf(t, s);
    
    memset(Hash, 0, sizeof(Hash));
    mh_sm3(Hash, Message0, 65);
    sprintf(s, "SM3 mh_sm3 Test %d\n", 65 * 8);
    t = (!memcmp(Hash, Hash_65Bytes, sizeof(Hash)));
    r_printf(t, s);
    
    memset(Hash, 0, sizeof(Hash));
    mh_sm3(Hash, Message0, 64*4+54);
    sprintf(s, "SM3 mh_sm3 Test %d\n", (64*4+54) * 8);
    t = (!memcmp(Hash, Hash_64_4_54Bytes, sizeof(Hash)));
    r_printf(t, s);
    
    memset(Hash, 0, sizeof(Hash));
    mh_sm3(Hash, Message0, 64*4+55);
    sprintf(s, "SM3 mh_sm3 Test %d\n", (64*4+55) * 8);
    t = (!memcmp(Hash, Hash_64_4_55Bytes, sizeof(Hash)));
    r_printf(t, s);
    
    memset(Hash, 0, sizeof(Hash));
    mh_sm3(Hash, Message0, 64*4+56);
    sprintf(s, "SM3 mh_sm3 Test %d\n", (64*4+56) * 8);
    t = (!memcmp(Hash, Hash_64_4_56Bytes, sizeof(Hash)));
    r_printf(t, s);
    
    pu8In = Message0;
    mh_sm3_starts(&ctx);
    
    len = 65;
    mh_sm3_update(&ctx, pu8In, len);
    pu8In += len;

    len = 62;
    mh_sm3_update(&ctx, pu8In, len);
    pu8In += len;
    
    len = 65;
    mh_sm3_update(&ctx, pu8In, len);
    pu8In += len;
    
    len = 65;
    mh_sm3_update(&ctx, pu8In, len);
    pu8In += len;
    
    len = 55;
    mh_sm3_update(&ctx, pu8In, len);
    pu8In += len;
    
    mh_sm3_finish(&ctx, Hash);
    
    sprintf(s, "SM3 update Test %d\n", (64*4+56) * 8);
    t = (!memcmp(Hash, Hash_64_4_56Bytes, sizeof(Hash)));
    r_printf(t, s);
    
    
    
    
}